package com.haircut.project.service.group.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.haircut.project.dao.config.ProjectConfigMapper;
import com.haircut.project.dao.group.ProjectGroupConfigRelMapper;
import com.haircut.project.dao.group.ProjectGroupMapper;
import com.haircut.project.model.group.ProjectGroup;
import com.haircut.project.model.group.ProjectGroupConfigRel;
import com.haircut.project.service.group.IProjectGroupService;
import com.haircut.project.vo.config.ConfigReqVo;
import com.haircut.project.vo.config.ConfigResVo;
import com.haircut.project.vo.group.*;
import com.haircut.sys.dao.user.SysUserMapper;
import com.haircut.sys.model.user.SysUser;
import com.haircut.sys.utils.PageUtils;
import com.haircut.sys.utils.user.SecurityUtils;
import com.haircut.sys.vo.user.LoginUserVo;
import com.modular.constant.BaseCodeDesc;
import com.modular.exception.ModularException;
import com.modular.result.PageResult;
import com.modular.utils.DBUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class ProjectGroupServiceImpl implements IProjectGroupService {
    @Autowired
    private ProjectGroupMapper projectGroupMapper;
    @Autowired
    private ProjectGroupConfigRelMapper projectGroupConfigRelMapper;
    @Autowired
    private ProjectConfigMapper projectConfigMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    @Qualifier("modularSnowflake")
    private Snowflake snowflake;

    /**
     * 查询所有数据
     * @param reqVo
     * @return
     */
    @Override
    public List<GroupListResVo> findAll(GroupListReqVo reqVo)
    {
        reqVo.setDeptId(SecurityUtils.getDeptId());
        reqVo.setGroupName(DBUtils.escapeQuryLikeParam(reqVo.getGroupName()));
        return projectGroupMapper.findAll(reqVo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveGroup(GroupSaveVo saveVo){
        LoginUserVo userVo = SecurityUtils.getLoginUser();
        Date date = DateUtil.date();
        hasSaveGroupName(saveVo.getGroupName(),null,userVo.getDeptId());
        ProjectGroup group = new ProjectGroup();
        group.setId(snowflake.nextIdStr());
        group.setDeptId(userVo.getDeptId());
        group.setGroupName(saveVo.getGroupName());
        group.setCreateDate(date);
        group.setCreateUserId(userVo.getUserId());
        group.setModifyDate(date);
        group.setModifyUserId(userVo.getUserId());
        projectGroupMapper.insert(group);
    }

    /**
     * 修改分组
     * @param saveVo
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void modifyGroup(GroupSaveVo saveVo)
    {
        LoginUserVo userVo = SecurityUtils.getLoginUser();
        Date date = DateUtil.date();
        hasSaveGroupName(saveVo.getGroupName(),saveVo.getId(),userVo.getDeptId());
        LambdaUpdateWrapper<ProjectGroup> modify = Wrappers.lambdaUpdate();
        modify.set(ProjectGroup::getGroupName,saveVo.getGroupName());
        modify.set(ProjectGroup::getModifyDate,date);
        modify.set(ProjectGroup::getModifyUserId,userVo.getUserId());
        modify.eq(ProjectGroup::getId,saveVo.getId());
        projectGroupMapper.update(modify);
    }

    /**
     * 删除分组
     * @param groupId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delGroup(String groupId)
    {
        projectGroupMapper.deleteById(groupId);

        LambdaQueryWrapper<ProjectGroupConfigRel> query = Wrappers.lambdaQuery();
        query.eq(ProjectGroupConfigRel::getGroupId,groupId);
        projectGroupConfigRelMapper.delete(query);
    }

    /**
     * 判断是否有重复的数据
     * @param groupName
     * @param id
     * @param deptId
     */
    private void hasSaveGroupName(String groupName,String id,String deptId){
        LambdaQueryWrapper<ProjectGroup> query = Wrappers.lambdaQuery();
        query.eq(ProjectGroup::getGroupName,groupName);
        query.eq(ProjectGroup::getDeptId,deptId);
        if(StrUtil.isNotBlank(id)){
            query.ne(ProjectGroup::getId,id);
        }
        boolean flg = projectGroupMapper.exists(query);
        if(flg){
            throw new ModularException(BaseCodeDesc.DEFATUL_MSG,"分类名称不能重复");
        }

    }

    /**
     * 保存配置分组信息
     * @param reqVo
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchSaveGroupConfigRel(BatchGroupConfigRelVo reqVo)
    {
        List<String> configIdList = reqVo.getList().stream().map(GroupConfigRelVo::getConfigId).distinct().toList();
        List<ProjectGroupConfigRel> list = projectGroupConfigRelMapper.findByGroupIdAndConfigIdList(reqVo.getGroupId(),configIdList);
        Map<String,ProjectGroupConfigRel> configRelMap = list.stream().collect(Collectors.toMap(ProjectGroupConfigRel::getConfigId,p->p));
        List<ProjectGroupConfigRel> insertList = new ArrayList<>();
        ProjectGroupConfigRel configRel = null;
        List<String> exsitConfigList = new ArrayList<>();
        ProjectGroupConfigRel dbConfigRel = null;
        for(GroupConfigRelVo relVo: reqVo.getList()){
            if(exsitConfigList.contains(relVo.getConfigId())){
                continue;
            }
            exsitConfigList.add(relVo.getConfigId());
            dbConfigRel = configRelMap.get(relVo.getConfigId());
            configRel = new ProjectGroupConfigRel();
            BeanUtils.copyProperties(relVo,configRel);
            configRel.setGroupId(reqVo.getGroupId());
            if(ObjectUtil.isNotNull(dbConfigRel)){
                configRel.setId(dbConfigRel.getId());
                projectGroupConfigRelMapper.updateById(configRel);
            }else{
                configRel.setId(snowflake.nextIdStr());
                insertList.add(configRel);
            }
        }
        if(CollUtil.isNotEmpty(insertList)){
            List<List<ProjectGroupConfigRel>> splitList = CollUtil.split(insertList,900);
            splitList.forEach(p->{
                projectGroupConfigRelMapper.batcInsert(p);
            });
        }

    }

    /**
     * 查询未配置西悉尼
     * @param reqVo
     * @return
     */
    @Override
    public PageResult<GroupConfigRelResVo> findGroupConfigPage(GroupConfigReqVo reqVo)
    {
        IPage<?> pageReq = Page.of(reqVo.getPageNum(),reqVo.getPageSize());
        ConfigReqVo configReqVo = new ConfigReqVo();
        BeanUtils.copyProperties(reqVo,configReqVo);
        Page<ConfigResVo> resVoPage = projectConfigMapper.findPage(pageReq,configReqVo);
        if(ObjectUtil.isNull(resVoPage) && CollUtil.isEmpty(resVoPage.getRecords())){
            return PageUtils.cover(reqVo);
        }
        List<String> configIdList = resVoPage.getRecords().stream().map(ConfigResVo::getId).toList();
        Map<String,ProjectGroupConfigRel> relMap = findConfigRel(reqVo.getGroupId(), configIdList);
        List<GroupConfigRelResVo> list = new ArrayList<>(resVoPage.getRecords().size());
        GroupConfigRelResVo relResVo = null;
        ProjectGroupConfigRel configRel = null;
        for(ConfigResVo resVo:resVoPage.getRecords()){
            relResVo = new GroupConfigRelResVo();
            relResVo.setConfigId(resVo.getId());
            relResVo.setConfigName(resVo.getProjectName());

            configRel = relMap.get(resVo.getId());
            if(ObjectUtil.isNotNull(configRel)){
                relResVo.setId(configRel.getId());
                relResVo.setTechnicianRate(configRel.getTechnicianRate());
            }
            list.add(relResVo);
        }

        return PageUtils.coverPageData(resVoPage,list);
    }

    /**
     * 查询配置
     * @param groupId
     * @param configIdList
     * @return
     */
    private Map<String,ProjectGroupConfigRel> findConfigRel(String groupId,List<String> configIdList){
        List<ProjectGroupConfigRel> list = projectGroupConfigRelMapper.findByGroupIdAndConfigIdList(groupId,configIdList);
        if(CollUtil.isEmpty(list)){
            return Collections.emptyMap();
        }
        return list.stream().collect(Collectors.toMap(ProjectGroupConfigRel::getConfigId,p->p,(v1,v2)->v1));
    }

    @Override
    public Map<String, ProjectGroup> findGroupByIdList(List<String> groupIdList)
    {
        if(CollUtil.isEmpty(groupIdList)){
            return Collections.emptyMap();
        }
        LambdaQueryWrapper<ProjectGroup> query = Wrappers.lambdaQuery();
        query.in(ProjectGroup::getId,groupIdList);
        List<ProjectGroup> groupList = projectGroupMapper.selectList(query);
        if(CollUtil.isEmpty(groupList)){
            return Collections.emptyMap();
        }
        return groupList.stream().collect(Collectors.toMap(ProjectGroup::getId,p->p));
    }
}
